﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ZHDJ.Core.Log;

namespace ZHDJ.Core.Util
{
    public class ImageHelper
    {
        #region 图片压缩保存

        /// <summary>
        /// 缩放图片并保存
        /// </summary>
        /// <param name="fromPath">图片路径</param>
        /// <param name="savePath">保存路径</param>
        /// <param name="width"></param>
        public static void HandlerByWidth(string fromPath, int width,string savePath="")
        {

            Handler(fromPath, a => SizeImageByWidth(a, width),savePath);
        }

        /// <summary>
        /// 缩放图片并保存
        /// </summary>
        /// <param name="fromPath">图片路径</param>
        /// <param name="savePath">保存路径</param>
        /// <param name="sizeImage"></param>
        public static void Handler(string fromPath, Func<Image, Image> sizeImage,string savePath="")
        {
            List<string> exts = new List<string>() {".png", ".jpg", ".jpeg", ".gif", ".bmp"};
            var fileEx = Path.GetExtension(fromPath).ToLower();
            if (!exts.Contains(fileEx))
            {
                //不是指定图片
                return;
            }

            if (string.IsNullOrEmpty(savePath))
            {
                savePath = fromPath.ToLower().IndexOf("_original") > 0 ? fromPath.ToLower().Replace("_original", "") : fromPath.Replace(fileEx, "_default" + fileEx);
            }
            var iSource = Image.FromFile(fromPath);
            var tFormat = iSource.RawFormat;
            
            var image = sizeImage(iSource);
            image.Save(savePath, tFormat);
        }

        #endregion

        #region 图片压缩处理实现
        /// <summary> 
        /// 按照指定高度缩放图片 
        /// </summary> 
        /// <param name="srcImage"></param> 
        /// <param name="iHeight"></param>  
        /// <returns></returns> 
        public static Bitmap SizeImageByHeight(Image srcImage, int iHeight)
        {
            try
            {
                if (srcImage.Height <= iHeight)
                {
                    //原图宽度小于指定值 不处理
                    return SizeImage(srcImage, srcImage.Width, srcImage.Height);
                }
                var iWidth = iHeight / srcImage.Height * srcImage.Width;
                return SizeImage(srcImage, iWidth, iHeight);
            }
            catch (Exception ex)
            {
                Log4netHelper.WriteLog(ex);
                srcImage.Dispose();
                return null;
            }
        }
        /// <summary> 
        /// 按照指定宽度缩放图片 
        /// </summary> 
        /// <param name="srcImage"></param> 
        /// <param name="iWidth"></param>  
        /// <returns></returns> 
        public static Bitmap SizeImageByWidth(Image srcImage, int iWidth)
        {
            try
            {
                
                if (srcImage.Width <= iWidth)
                {
                    //原图宽度小于指定值 不处理
                    return SizeImage(srcImage, srcImage.Width, srcImage.Height);
                }

                var iHeight =  iWidth/(double)srcImage.Width * srcImage.Height;
                
                return SizeImage(srcImage, iWidth, int.Parse(Math.Round(iHeight).ToString()));
            }
            catch (Exception ex)
            {
                Log4netHelper.WriteLog(ex);
                return null;
            }
        }
        /// <summary> 
        /// 按照指定大小缩放图片 (图片可能会变形)
        /// </summary> 
        /// <param name="srcImage"></param> 
        /// <param name="iWidth"></param> 
        /// <param name="iHeight"></param> 
        /// <returns></returns> 
        public static Bitmap SizeImage(Image srcImage, int iWidth, int iHeight)
        {
            try
            {
                // 要保存到的图片 
                Bitmap b = new Bitmap(iWidth, iHeight);
                Graphics g = Graphics.FromImage(b);
                // 插值算法的质量 
                g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                g.DrawImage(srcImage, new Rectangle(0, 0, iWidth, iHeight),
                    new Rectangle(0, 0, srcImage.Width, srcImage.Height), GraphicsUnit.Pixel);
                g.Dispose();
                return b;
            }
            catch (Exception ex)
            {
                Log4netHelper.WriteLog(ex);
                return null;
            }
        }

        /// <summary> 
        /// 按照最大宽度和最大高度缩放图片
        /// </summary> 
        /// <param name="srcImage"></param> 
        /// <param name="maxWidth"></param> 
        /// <param name="maxHeight"></param> 
        /// <returns></returns> 
        public static Bitmap SizeAutoImage(Image srcImage, int maxWidth, int maxHeight)
        {
            try
            {
                var imageWidth = srcImage.Width;
                var imageHeight = srcImage.Height;
                if (maxWidth <= imageWidth && maxHeight > imageHeight)
                {
                    //不处理
                    return SizeImage(srcImage, imageWidth, imageHeight);
                }
                double percent = 1.0;
                if (imageWidth > imageHeight)
                {
                    //以宽度进行缩放
                    percent= (double)maxHeight/ (double)imageHeight;

                }
                else
                {
                    //以高度进行缩放
                    percent = (double)maxWidth  / (double)imageWidth;
                }
                return PercentImage( srcImage, percent);
            }
            catch (Exception ex)
            {
                Log4netHelper.WriteLog(ex);
                return null;
            }
        }

        /// <summary> 
        /// 按照比例缩小图片 
        /// </summary> 
        /// <param name="srcImage">要缩小的图片</param> 
        /// <param name="percent">缩小比例</param> 
        /// <returns>缩小后的结果</returns> 
        public static Bitmap PercentImage(Image srcImage, double percent)
        {
            // 缩小后的高度 
            int newH = int.Parse(Math.Round(srcImage.Height*percent).ToString());
            // 缩小后的宽度 
            int newW = int.Parse(Math.Round(srcImage.Width*percent).ToString());
            try
            {
                // 要保存到的图片 
                Bitmap b = new Bitmap(newW, newH);
                Graphics g = Graphics.FromImage(b);
                // 插值算法的质量 
                g.InterpolationMode = InterpolationMode.Default;
                g.DrawImage(srcImage, new Rectangle(0, 0, newW, newH),
                    new Rectangle(0, 0, srcImage.Width, srcImage.Height), GraphicsUnit.Pixel);
                g.Dispose();
                return b;
            }
            catch (Exception ex)
            {
                Log4netHelper.WriteLog(ex);
                return null;
            }
        }

        /// <summary> 
        /// 按照指定大小缩放图片，但是为了保证图片宽高比自动截取 
        /// </summary> 
        /// <param name="srcImage"></param> 
        /// <param name="iWidth"></param> 
        /// <param name="iHeight"></param> 
        /// <returns></returns> 
        public static Bitmap SizeImageWithOldPercent(Image srcImage, int iWidth, int iHeight)
        {
            try
            {
                // 要截取图片的宽度（临时图片） 
                int newW = srcImage.Width;
                // 要截取图片的高度（临时图片） 
                int newH = srcImage.Height;
                // 截取开始横坐标（临时图片） 
                int newX = 0;
                // 截取开始纵坐标（临时图片） 
                int newY = 0;
                // 截取比例（临时图片） 
                double whPercent = 1;
                whPercent = ((double)iWidth / (double)iHeight) * ((double)srcImage.Height / (double)srcImage.Width);
                if (whPercent > 1)
                {
                    // 当前图片宽度对于要截取比例过大时 
                    newW = int.Parse(Math.Round(srcImage.Width / whPercent).ToString());
                }
                else if (whPercent < 1)
                {
                    // 当前图片高度对于要截取比例过大时 
                    newH = int.Parse(Math.Round(srcImage.Height * whPercent).ToString());
                }
                if (newW != srcImage.Width)
                {
                    // 宽度有变化时，调整开始截取的横坐标 
                    newX = Math.Abs(int.Parse(Math.Round(((double)srcImage.Width - newW) / 2).ToString()));
                }
                else if (newH == srcImage.Height)
                {
                    // 高度有变化时，调整开始截取的纵坐标 
                    newY = Math.Abs(int.Parse(Math.Round(((double)srcImage.Height - (double)newH) / 2).ToString()));
                }
                // 取得符合比例的临时文件 
                Bitmap cutedImage = CutImage(srcImage, newX, newY, newW, newH);
                // 保存到的文件 
                Bitmap b = new Bitmap(iWidth, iHeight);
                Graphics g = Graphics.FromImage(b);
                // 插值算法的质量 
                g.InterpolationMode = InterpolationMode.Default;
                g.DrawImage(cutedImage, new Rectangle(0, 0, iWidth, iHeight), new Rectangle(0, 0, cutedImage.Width, cutedImage.Height), GraphicsUnit.Pixel);
                g.Dispose();
                return b;
            }
            catch (Exception ex)
            {
                Log4netHelper.WriteLog(ex);
                return null;
            }
        }

        /// <summary> 
        /// jpeg图片压缩 
        /// </summary> 
        /// <param name="sFile"></param> 
        /// <param name="outPath"></param> 
        /// <param name="flag"></param> 
        /// <returns></returns> 
        public static bool GetPicThumbnail(string sFile, string outPath, int flag)
        {
            System.Drawing.Image iSource = System.Drawing.Image.FromFile(sFile);
            ImageFormat tFormat = iSource.RawFormat;
            //以下代码为保存图片时，设置压缩质量 
            EncoderParameters ep = new EncoderParameters();
            long[] qy = new long[1];
            qy[0] = flag;//设置压缩的比例1-100 
            EncoderParameter eParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, qy);
            ep.Param[0] = eParam;
            try
            {
                ImageCodecInfo[] arrayICI = ImageCodecInfo.GetImageEncoders();
                ImageCodecInfo jpegICIinfo = null;
                for (int x = 0; x < arrayICI.Length; x++)
                {
                    if (arrayICI[x].FormatDescription.Equals("JPEG"))
                    {
                        jpegICIinfo = arrayICI[x];
                        break;
                    }
                }
                if (jpegICIinfo != null)
                {
                    iSource.Save(outPath, jpegICIinfo, ep);//dFile是压缩后的新路径 
                }
                else
                {
                    iSource.Save(outPath, tFormat);
                }
                return true;
            }
            catch( Exception ex)
            {
                Log4netHelper.WriteLog(ex);
                return false;
            }
            finally
            {
                iSource.Dispose();
                iSource.Dispose();
            }
        }

        /// <summary> 
        /// 剪裁 -- 用GDI+ 
        /// </summary> 
        /// <param name="b">原始Bitmap</param> 
        /// <param name="StartX">开始坐标X</param> 
        /// <param name="StartY">开始坐标Y</param> 
        /// <param name="iWidth">宽度</param> 
        /// <param name="iHeight">高度</param> 
        /// <returns>剪裁后的Bitmap</returns> 
        public static Bitmap CutImage(Image b, int StartX, int StartY, int iWidth, int iHeight)
        {
            if (b == null)
            {
                return null;
            }
            int w = b.Width;
            int h = b.Height;
            if (StartX >= w || StartY >= h)
            {
                // 开始截取坐标过大时，结束处理 
                return null;
            }
            if (StartX + iWidth > w)
            {
                // 宽度过大时只截取到最大大小 
                iWidth = w - StartX;
            }
            if (StartY + iHeight > h)
            {
                // 高度过大时只截取到最大大小 
                iHeight = h - StartY;
            }
            try
            {
                Bitmap bmpOut = new Bitmap(iWidth, iHeight);
                Graphics g = Graphics.FromImage(bmpOut);
                g.DrawImage(b, new Rectangle(0, 0, iWidth, iHeight), new Rectangle(StartX, StartY, iWidth, iHeight), GraphicsUnit.Pixel);
                g.Dispose();
                return bmpOut;
            }
            catch (Exception ex)
            {
                Log4netHelper.WriteLog(ex);
                return null;
            }
        }
        #endregion
    }

    public class ImageHandlerPara
    {

        /// <summary>
        /// 标准宽度
        /// </summary>
        public int DefaultWidth { get; set; }
        /// <summary>
        /// 小图宽度
        /// </summary>
        public int SmallWidth { get; set; }
    }
}